import { IMDCtrlController, IMDCtrlStore } from '@/core';
import {
	ICodeListItem,
	IEvent,
	IMDCtrlAbility,
	IMDCtrlControllerParams,
	IParam,
	MDCtrlActionType,
} from '@/core/interface';
import { MDCtrlControllerBase } from './md-ctrl-controller-base';

/**
 * 多数据部件控制器
 *
 * @export
 * @class MDCtrlController
 * @extends {(MDCtrlControllerBase<T | MDCtrlActionType, S, A>)}
 * @implements {IMDCtrlController<S, A>}
 * @template T
 * @template S
 * @template A
 */
export class MDCtrlController<
		T,
		S extends IMDCtrlStore,
		A extends IMDCtrlAbility
	>
	extends MDCtrlControllerBase<T | MDCtrlActionType, S, A>
	implements IMDCtrlController<S, A>
{
	/**
	 * 数据备份
	 *
	 * @protected
	 * @type {IParam}
	 * @memberof MDCtrlController
	 */
	protected backData: IParam = [];

	/**
	 * Creates an instance of MDCtrlController.
	 * @param {IMDCtrlControllerParams<ListActionType, IListAbility>} params
	 * @memberof MDCtrlController
	 */
	public constructor(
		params: IMDCtrlControllerParams<MDCtrlActionType, IMDCtrlAbility>
	) {
		super(params);
		this.ctrlInit(params);
	}

	/**
	 * 处理加载数据变化
	 *
	 * @protected
	 * @param {IParam[]} data
	 * @memberof MDCtrlController
	 */
	protected handleLoadDataChange(data: IParam[], tag?: string): void {
		super.handleLoadDataChange(data, tag);
		if (tag == 'loadMore') {
			this.store.data.push(...data);
		} else {
			this.backData = data;
			this.store.data = data;
		}
		this.handleGroup();
		this.handleDefaultSelect();
	}

	/**
	 * 自动分组
	 *
	 * @protected
	 * @memberof MDCtrlController
	 */
	protected async handleAutoGroup() {
		if (this.backData.length === 0) {
			return;
		}
		//  分组属性标识
		const field = this.model.groupField as string;
		//  分组属性代码表
		const fieldCodeList = this.model.groupFieldCodeListTag;
		//  分组列标识
		const dataIndex = this.model.groupDataIndex as string;
		const resultMap: Map<string, IParam[]> = new Map();
		const codeItems: IParam[] = [];
		if (fieldCodeList) {
			const result = await App.getAppCodeListHelper().getCodeListItems(
				fieldCodeList
			);
			if (result.ok) {
				codeItems.push(...result.data);
			}
		}
		this.backData.forEach((item: IParam) => {
			const items = resultMap.get(item[field]) || [];
			items.push(item);
			resultMap.set(item[field], items);
		});
		const resultItems: IParam[] = [];
		resultMap.forEach((value: IParam[], key: string) => {
			const item =
				codeItems.length > 0
					? codeItems.find((item: IParam) => item.value === key)
					: { text: key };
			resultItems.push({
				key: `group-item__${key}`,
				srfkey: `group-item__${key}`,
				srfmajortext: item ? item.text : App.ts('widget.md.other', '其他'),
				[dataIndex]: item ? item.text : App.ts('widget.md.other', '其他'),
				isGroupItem: true,
				children: value,
			});
		});
		this.store.data = resultItems;
	}

	/**
	 * 代码表分组
	 *
	 * @protected
	 * @return {*}
	 * @memberof MDCtrlController
	 */
	protected async handleCodeListGroup() {
		//  分组代码表标识
		const codeListTag = this.model.groupCodeListTag as string;
		//  分组属性标识
		const field = this.model.groupField as string;
		//  分组列标识
		const dataIndex = this.model.groupDataIndex as string;
		if (!codeListTag) {
			return;
		}
		const { context, viewParams } = this.store;
		const result = await App.getAppCodeListHelper().getCodeListItems(
			codeListTag,
			context,
			viewParams
		);
		if (!result.ok || result.data.length === 0) {
			return;
		}
		const keys: (string | number)[] = result.data.map(
			(d: ICodeListItem) => d.value
		);
		const resultItems: IParam[] = [];
		result.data.forEach((item: ICodeListItem) => {
			const items: IParam[] = this.backData.filter(
				(d: IParam) => d[field] === item.value
			);
			resultItems.push({
				key: `group-item__${item.value}`,
				srfkey: `group-item__${item.value}`,
				srfmajortext: item.text,
				[dataIndex]: item.text,
				isGroupItem: true,
				children: items,
			});
		});
		const otherItems = this.backData.filter(
			(d: IParam) => keys.indexOf(d[field]) === -1
		);
		if (otherItems.length > 0) {
			resultItems.push({
				key: `group-other-item`,
				srfkey: `group-other-item`,
				[dataIndex]: App.ts('widget.md.other', '其他'),
				isGroupItem: true,
				children: otherItems,
			});
		}
		this.store.data = resultItems;
	}

	/**
	 * 加载更多
	 *
	 * @memberof MDCtrlController
	 */
	public loadMore() {
		this.store.curPage += 1;
		this.load({}, 'loadMore');
	}

	/**
	 *
	 *
	 * @param {(IParam | undefined)} [args]
	 * @return {*}  {Promise<boolean>}
	 * @memberof MDCtrlController
	 */
	public async refresh(args?: IParam | undefined): Promise<boolean> {
		try {
			const result = await this.load({ srfpagereset: true }, 'refresh');
			if (result.ok) {
				return true;
			}
		} catch (error) {
			return false;
		}
		return false;
	}

	/**
	 * 列表项激活
	 *
	 * @param {IParam} item
	 * @param {MouseEvent} event
	 * @memberof MDCtrlController
	 */
	itemActive(item: IParam, event: MouseEvent) {
		const selections = this.store.selections;
		if (this.singleSelect) {
			selections.length = 0;
			selections.push(item);
		} else {
			const index = selections.findIndex(
				(select: IParam) => select.srfkey === item.srfkey
			);
			//	未选中
			if (index === -1) {
				this.store.selections.push(item);
			} else {
				this.store.selections.splice(index, 1);
			}
		}
		this.emit('selectionChange', this.getData());
		this.emit('dataActive', [item]);
	}

	/**
	 * 选中数据
	 *
	 * @param {IParam[]} selections
	 * @memberof MDCtrlController
	 */
	selectionChange(selections: IParam[]) {
		this.store.selections = selections;
		this.emit('selectionChange', this.getData());
	}

	/**
	 * 处理多数据组件行为
	 *
	 * @param {IEvent<string>} actionParam 行为参数
	 * @memberof MDCtrlController
	 */
	public itemActionActive(actionParam: IEvent<string>): void {
		const { data } = actionParam;
		const { context, viewParams } = this.store;
		App.getViewLogicHelper().executeViewLogic(
			context,
			viewParams,
			[data.item],
			data.event,
			this.getAbility(),
			data.logic
		);
	}
}
